require 'optparse'
require 'ruby-beautify'
require 'tempfile'
require_relative './file_formatter'
require_relative './method_remover'
require_relative './include_line_injector'

module RailsEnhancer
  class ControllerGenerator < Rails::Generators::Base
    source_root File.expand_path('../templates', __FILE__)
    argument :controller_file_name, :type => :string, :default => 'application'

    def init
      @controller_obj = Object.const_get(controller_file_name.classify)
      @controller_path = controller_file_name.split('/')
      @class_name = @controller_path.pop
      @methods_map = []
    end

    def build_path_to_controller
      @path_to_controller = Pathname('app/controllers/').join(*@controller_path)
    end

    def create_dir_structure
      FileUtils.mkpath(@path_to_controller.join("#{@class_name}_actions").to_s)
    end

    def parse_controller
      @controller_obj.instance_methods(false).each do |e|
        source_code = extract_method_source(e)
        @methods_map << {name: e, start_line: @controller_obj.instance_method(e).source_location.last, lines_count: source_code.lines.size}
        generate_action_file(source_code, e)
      end
    end

    def remove_old_actions
      RailsEnhancer::MethodRemover
          .new(@methods_map, @path_to_controller.join("#{controller_file_name}.rb").to_s, controller_file_name)
          .remove_all
    end

    def inject_module
      RailsEnhancer::IncludeLineInjector
          .new(@path_to_controller.join("#{controller_file_name}.rb").to_s, controller_file_name)
          .run
    end

    def format_rb_files
      @controller_obj.instance_methods(false).each do |e|
        RailsEnhancer::FileFormatter
            .new(@path_to_controller.join("#{@class_name}_actions", "#{e}.rb"))
            .format_rb_file()
      end

      RailsEnhancer::FileFormatter
          .new(@path_to_controller.join("#{controller_file_name}.rb").to_s)
          .format_rb_file()
    end

    private

    def extract_method_source(name)
      @controller_obj.instance_method(name).source
    end

    def generate_action_file(content, name)
      @name = name.to_s.classify
      @modules = @controller_path.map { |e| e.to_s.classify } + ["#{@class_name.to_s.classify}Actions"]
      @content = content.to_s.gsub("def #{name}", 'def action')
      template 'action_class_template.rb.erb', @path_to_controller.join("#{@class_name}_actions", "#{name}.rb")
    end
  end
end